[PR]

水無瀬の部屋 > Programming > sample > atlnk > shitemid.cpp
最終更新日: 2007/03/24

   1: //*********************************************************
   2: // プロジェクト: atlnk - @link.target
   3: //   ファイル名: shitemid.cpp
   4: //*********************************************************
   5: #include "shitemid.h"          //
   6: #include <misc/atoffset.h>
   7: 
   8: 
   9: //---------------------------------------------------------
  10: // マクロ関数 の 定義
  11: //---------------------------------------------------------
  12: #define NEXTITEMID( ptr, offset )  (&atoffset( ITEMIDLIST, (ptr), (offset) ))
  13: 
  14: 
  15: //---------------------------------------------------------
  16: // ファイルスコープ関数 の 宣言
  17: //---------------------------------------------------------
  18: static bool        IsValidItemIDList( const ITEMIDLIST *pidl );
  19: static ITEMIDLIST *ITEMIDLIST_GetNextItemID( const ITEMIDLIST *pidl );
  20: static bool        ShellLink_GetTargetFile( const char *LinkFile, ITEMIDLIST **ppidl );
  21: static bool        OpenParentIDList( IMalloc *pMalloc, const ITEMIDLIST *pidl, const char *verb );
  22: static HINSTANCE   ITEMIDLIST_ShellExecute( HWND hWnd, const char *verb, const ITEMIDLIST *pidl, const char *lpParameters, const char *lpDirectory, int nShowCmd );
  23: 
  24: 
  25: //*********************************************************
  26: // OpenLinkTargetLocation()
  27: // ショートカット の リンク先 がある フォルダ を 動詞 verb で 開く
  28: //*********************************************************
  29: bool
  30: OpenLinkTargetLocation
  31: 	(
  32: 		      int    argc,
  33: 		      char **argv,
  34: 		const char  *verb  // 動詞
  35: 	)
  36: {
  37: 	// パラメタの仮定
  38: 	ASSERT( IsValidArgcArgv( argc, argv ) );
  39: 	ASSERT( !verb || IsValidStringPtr( verb ) );
  40: 
  41: 	// シェル・アロケータの取得
  42: 	IMalloc *pMalloc;
  43: 	if ( NOERROR != SHGetMalloc( &pMalloc ) )
  44: 	{
  45: 		return false;
  46: 	}
  47: 
  48: 	// 
  49: 	{for( int i = 0; i < argc; ++i )
  50: 	{
  51: 		ASSERT( IsPathExist( argv[ i ] ) );
  52: 		
  53: 		if ( IsPathFile( argv[ i ] ) )
  54: 		{
  55: 			// リンク先を取得
  56: 			ITEMIDLIST *pidl = null;
  57: 			if ( ShellLink_GetTargetFile( argv[ i ], &pidl ) )
  58: 			{
  59: 				ASSERT( IsValidItemIDList( pidl ) );
  60: 
  61: 				// リンク先があるフォルダを開く
  62: 				VERIFY( OpenParentIDList( pMalloc, pidl, verb ) );
  63: 
  64: 				pMalloc->Free( pidl );
  65: 			}
  66: 		}
  67: 	}}
  68: 
  69: 	// シェル・アロケータの解放
  70: 	pMalloc->HeapMinimize();
  71: 	pMalloc->Release();
  72: 
  73: 	// 終了
  74: 	return true;
  75: }//OpenLinkTargetLocation
  76: 
  77: 
  78: //******************************************************************************************************************
  79: // private
  80: //******************************************************************************************************************
  81: static bool        OpenIDList( const ITEMIDLIST *pidl, const char *verb );
  82: static ITEMIDLIST *GetParentIDList( IMalloc *pMalloc, const ITEMIDLIST *pidl );
  83: static ITEMIDLIST *GetNextIDList( const ITEMIDLIST *pidl );
  84: 
  85: 
  86: //*********************************************************
  87: // OpenParentIDList
  88: // 親フォルダ(オブジェクトが存在するフォルダ)を開く
  89: //*********************************************************
  90: static
  91: bool
  92: OpenParentIDList
  93: 	(
  94: 		      IMalloc    *pMalloc,
  95: 		const ITEMIDLIST *pidl,
  96: 		const char       *verb
  97: 	)
  98: {
  99: 	// パラメタの仮定
 100: 	ASSERT( IsValidPtr( pMalloc, sizeof( *pMalloc ) ) );
 101: 	ASSERT( IsValidItemIDList( pidl ) );
 102: 	ASSERT( IsValidStringPtr( verb ) );
 103: 
 104: 	// 親フォルダを取得
 105: 	ITEMIDLIST *pidlParent = GetParentIDList( pMalloc, pidl );
 106: 	if ( !pidlParent )
 107: 	{
 108: 		return false; //
 109: 	}
 110: 	ASSERT( IsValidItemIDList( pidlParent ) );
 111: 
 112: 	// 親フォルダを開く
 113: 	OpenIDList( pidlParent, verb );
 114: 
 115: 	// 親フォルダの解放
 116: 	pMalloc->Free( pidlParent );
 117: 
 118: 	// 成功終了
 119: 	return true;
 120: }//OpenParentIDList
 121: 
 122: //*********************************************************
 123: // OpenIDList
 124: // 指定のフォルダ pidl を開く
 125: // => 指定の pidl に何かする
 126: //*********************************************************
 127: static
 128: bool
 129: OpenIDList
 130: 	(
 131: 		const ITEMIDLIST *pidl,
 132: 		const char       *verb
 133: 	)
 134: {
 135: 	// パラメタの仮定
 136: 	ASSERT( IsValidItemIDList( pidl ) );
 137: 	ASSERT( IsValidStringPtr( verb ) );
 138: 	
 139: 
 140: 	// 指定の pidl を開く
 141: 	// ShellExecuteEx() より ShellExecute() の方が
 142: 	// 古い OS で安定動作するようなので可能であれば ShellExecute() を使う
 143: 	// 例えば "c:\\windows\\command\\" を
 144: 	// "c:\\windows\\command.com" と間違えないように
 145: 	// if ( GetPathFromIDList( pidl, path, numof(path) ) )
 146: 	// {
 147: 	// 	ASSERT( IsPathDirectory( path ) );
 148: 	// 	ASSERT( 0 != strlen( path ) );
 149: 	// strncat( path, ".\\", sizeof(path) - strlen(path) - 1 );
 150: 
 151: 	SHELLEXECUTEINFO sei;
 152: 	memzero( &sei, sizeof( sei ) );
 153: 	sei.cbSize       = sizeof( sei );
 154: 	sei.fMask        = SEE_MASK_IDLIST;
 155: 	sei.hwnd         = HWND_DESKTOP;
 156: 	sei.nShow        = SW_SHOWNORMAL;
 157: 	sei.lpVerb       = verb;
 158: 	sei.lpFile       = null;
 159: 	sei.lpParameters = null;
 160: 	sei.lpDirectory  = null;
 161: 	sei.lpIDList     = const_cast<ITEMIDLIST *>( pidl );
 162: 	VERIFY( ShellExecuteEx( &sei ) );
 163: 
 164: 	return SHELLEXECUTE_SUCCEEDED( sei.hInstApp );
 165: }//OpenIDList
 166: 
 167: //*********************************************************
 168: // GetParentIDList
 169: // 親フォルダ(オブジェクトが存在するフォルダ)を取得
 170: //*********************************************************
 171: static
 172: ITEMIDLIST *
 173: GetParentIDList
 174: 	(
 175: 		      IMalloc    *pMalloc,
 176: 		const ITEMIDLIST *pidl
 177: 	) 
 178: {
 179: 	// パラメタの仮定
 180: 	ASSERT( IsValidPtr( pMalloc, sizeof( *pMalloc ) ) );
 181: 	ASSERT( IsValidItemIDList( pidl ) );
 182: 
 183: 	//
 184: 	int cbPre = 0;  // 直前の項目サイズ
 185: 	int cbTotal;    // ここまでのサイズ
 186: 	int cbTotalPre; // 直前までのサイズ
 187: 
 188: 	// pidlParent に必要なサイズを試算
 189: 	{
 190: 		cbTotal    = 0;
 191: 		cbTotalPre = 0;
 192: 
 193: 		int cb;
 194: 		const ITEMIDLIST *pidlNext = pidl;
 195: 		while( 0 != (cb = pidlNext->mkid.cb) )
 196: 		{
 197: 			ASSERT( (0 < cb) && (cb <= USHRT_MAX) );
 198: 
 199: 			cbPre       = cb;
 200: 			cbTotalPre  = cbTotal;
 201: 			cbTotal    += cb;
 202: 
 203: 			pidlNext = ITEMIDLIST_GetNextItemID( pidlNext );
 204: 			ASSERT( cbTotal == cbTotalPre + cbPre );
 205: 		}
 206: 		ASSERT( 0 == pidlNext->mkid.cb );
 207: 
 208: 		ASSERT( IsValidPtr( (ITEMIDLIST *)pidl, cbTotal + sizeof( pidlNext->mkid.cb ) ) );
 209: 		cbTotal = cbTotalPre + sizeof( pidlNext->mkid.cb );
 210: 		ASSERT( IsValidPtr( (ITEMIDLIST *)pidl, cbTotal ) );
 211: 	}
 212: 
 213: 	// pidlParent の構築
 214: 	ITEMIDLIST *pidlParent = (ITEMIDLIST *)pMalloc->Alloc( cbTotal );
 215: 	if ( !pidlParent )
 216: 	{
 217: 		// 領域の確保に失敗
 218: 		return null;
 219: 	}
 220: 	ASSERT( IsValidPtr( pidlParent, cbTotal ) );
 221: 
 222: 	// 親フォルダまで複写
 223: 	memmove( pidlParent, pidl, cbTotal );
 224: 	ITEMIDLIST *tail = NEXTITEMID( pidlParent, cbTotalPre );
 225: 	ASSERT( tail->mkid.cb == cbPre );
 226: 	tail->mkid.cb = 0;
 227: 
 228: 	ASSERT( IsValidItemIDList( pidlParent ) );
 229: 	ASSERT( IsValidItemIDList( pidl ) );
 230: 
 231: 	return pidlParent;
 232: }//GetParentIDList
 233: 
 234: 
 235: //******************************************************************************************************************
 236: // util ( shell link )
 237: //******************************************************************************************************************
 238: //*********************************************************
 239: // ShellLink_GetTargetFile
 240: // ショートカット path が指すオブジェクトへの ITEMIDLIST を取得する。
 241: //*********************************************************
 242: static
 243: bool
 244: ShellLink_GetTargetFile
 245: 	(
 246: 		const char        *path,
 247: 		      ITEMIDLIST **ppidl
 248: 	)
 249: {
 250: 	// パラメタの仮定
 251: 	ASSERT( IsPathFile( path ) );
 252: 	ASSERT( IsValidPtr( ppidl, sizeof( *ppidl ) ) );
 253: 
 254: 	//
 255: 	*ppidl = null;
 256: 
 257: 	// ショートカット path へのインタフェイスを取得する
 258: 	IShellLink *psl = LoadShellLinkInstance( CLSCTX_INPROC_SERVER, path, STGM_READ );
 259: 	if ( !psl )
 260: 	{
 261: 		return false; // [失敗]
 262: 	}
 263: 	ASSERT( IsValidPtr( psl, sizeof( *psl ) ) );
 264: 
 265: 	// リンク先を取得
 266: 	if ( S_OK != psl->GetIDList( ppidl ) )
 267: 	{
 268: 		psl->Release();
 269: 		*ppidl = null;
 270: 		return false; // [失敗]
 271: 	}
 272: 
 273: 	psl->Release();
 274: 	ASSERT( IsValidPtr( ppidl, sizeof( *ppidl ) ) );
 275: 	ASSERT( IsValidItemIDList( *ppidl ) );
 276: 	return boolean_cast( *ppidl ); 	// [成功]
 277: }//ShellLink_GetTargetFile
 278: 
 279: 
 280: //******************************************************************************************************************
 281: //
 282: //******************************************************************************************************************
 283: //*********************************************************
 284: // IsValidItemIDList
 285: //*********************************************************
 286: static 
 287: bool
 288: IsValidItemIDList
 289: 	(
 290: 		const ITEMIDLIST *pidl
 291: 	)
 292: {
 293: 	VALID_TEST( pidl );
 294: 	VALID_TEST( IsValidReadPtr( pidl, sizeof( *pidl ) ) );
 295: 
 296: 	//
 297: 	int cbTotal = 0;
 298: 	{
 299: 		int cb;
 300: 		const ITEMIDLIST *p = pidl;
 301: 		while( 0 != (cb = p->mkid.cb) )
 302: 		{
 303: 			ASSERT( (0 < cb) && (cb <= USHRT_MAX) );
 304: 			VALID_TEST( IsValidReadPtr( p, cb ) );
 305: 
 306: 			// 次の項目の位置を指す
 307: 			cbTotal += cb;
 308: 			p = NEXTITEMID( p, cb );
 309: 		}
 310: 		ASSERT( 0 == p->mkid.cb );
 311: 		cbTotal += sizeof( p->mkid.cb );	
 312: 	}
 313: 
 314: 	//
 315: 	VALID_TEST( IsValidReadPtr( pidl, cbTotal ) );
 316: 	
 317: 	return true;
 318: }//IsValidItemIDList
 319: 
 320: //*********************************************************
 321: // ITEMIDLIST_GetNextItemID
 322: //*********************************************************
 323: static
 324: ITEMIDLIST *
 325: ITEMIDLIST_GetNextItemID
 326: 	(
 327: 		const ITEMIDLIST *pidl
 328: 	)
 329: {
 330: 	// パラメタの仮定
 331: 	ASSERT( IsValidItemIDList( pidl ) );
 332: 
 333: 	// 先頭項目のサイズを取得
 334: 	const int cb = pidl->mkid.cb;
 335: 	if ( cb <= 0 ) 
 336: 	{
 337: 		return null;
 338: 	}
 339: 	ASSERT( (0 < cb) && (cb <= USHRT_MAX) );
 340: 
 341: 	// 次の項目の位置を指す
 342: 	ITEMIDLIST *pidlNext = NEXTITEMID( pidl, cb );
 343: 	ASSERT( IsValidItemIDList( pidlNext ) );
 344: 
 345: 	return pidlNext;
 346: }//ITEMIDLIST_GetNextItemID
 347: 
 348: 
 349: //** end **

参照:


Google
ご意見・ご感想をお聞かせ下さい。匿名で送信できます。

 * 返信が必要な場合には postmaster@katsura-kotonoha.sakura.ne.jp へ直接メールしてください。

水無瀬の部屋 > sample > atlnk > shitemid.cpp

このページは cpp2web が出力しました。
水無瀬 優 postmaster@katsura-kotonoha.sakura.ne.jp
http://katsura-kotonoha.sakura.ne.jp/prog/code/atlnk/shitemid_cpp.shtml
『新妻LOVELY×CATION』を応援しています!